Reversing Hyperscore v4.0
By: Gabri3l / ARTeam
http://cracking.accessroot.com

Unpacking Hyperscore v4.0 and Defeating it's Protection

The Target:
Hyperscore v4.0
http://www.harmonylinemusic.com/
The Tools:
PEID, Ollydbg 1.10
The Protection:
Registration Key

Other Information:
This tutorial was partially written in the ARTeam Request forum so you may have already read part of it. I added more information and compiled it all together to make it one tutorial. In this tutorial we will cover how to unpack PC-Guard 5.0 by using exceptions. We will also cover how to use the Call Stack in Olly and how the Call Stack can be used to understand and reverse a programs protection.

Best viewed in Firefox at 1280x1024

Intro:

All the tools you will need can be found online:
http://home.t-online.de/home/Ollydbg/

As usual we will start by opening up the target application in PEID. PEID shows that it is packed with the PC-Guard protection. If your PEID does not recognize the protection as PC-Guard 5.0, stop by the ARTeam forums and search for the complete "userdb.txt" for PEID. Well we know that the program is protected so before we can think about reversing it we need to start by unpacking it.



Body:

Unpacking PC-Guard 5.0:
(This may not work for other programs protected with PCGuard 5.x but it worked for this one)

1. Open up Hyperscore in Olly
2. In Debugging Options->Exceptions choose:
Memory Access Violations in Kernel32
INT3 breaks
Memory Access Violations
3. Read Beginner Tutorial #6 by Shub-Nigurrath for more detailed information on protectors. But in general for a lot of
packed programs, if you can find out where the program unpacks the code and then break after the code is unpacked, you can put a breakpoint on the unpacked code section and just wait until the program jumps to the OEP. That is how we are going to find the OEP for PC-Guard.
4. PCGuard 5.0 unpacks the code section, and we can see the .code section by choosing View->Memory. Double-click the [Hyperscore .code] section. You will be here:

CODE
00401000 C6 ??? ; Unknown command
00401001 AB STOS DWORD PTR ES:[EDI]
00401002 EF OUT DX,EAX ; I/O command
00401003 70 11 JO SHORT Hypersco.00401016
00401005 1D 53D8CAA3 SBB EAX,A3CAD853
0040100A FF77 1E PUSH DWORD PTR DS:[EDI+1E]
0040100D A5 MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ES>
0040100E D7 XLAT BYTE PTR DS:[EBX+AL]
0040100F 06 PUSH ES
00401010 D9AD 75FE757F FLDCW WORD PTR SS:[EBP+7F75FE75]
00401016 27 DAA
00401017 A5 MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ES>
00401018 -7F 8B JG SHORT Hypersco.00400FA5
0040101A 2E:F1 INT1 ; Superfluous prefix
0040101C 39D5 CMP EBP,EDX
0040101E 1E PUSH DS
0040101F ^75 E4 JNZ SHORT Hypersco.00401005
00401021 B4 4B MOV AH,4B
00401023 60 PUSHAD
00401024 65:60 PUSHAD ; Superfluous prefix
00401026 C40B LES ECX,FWORD PTR DS:[EBX] ; Modification of segment register
00401028 EA 9EA4B57D 5BE3 JMP FAR E35B:7DB5A49E ; Far jump
0040102F 87B5 1C4E9D9F XCHG DWORD PTR SS:[EBP+9F9D4E1C],ESI
00401035 1D 593E8222 SBB EAX,22823E59
0040103A F5 CMC
0040103B FA CLI
0040103C 15 57B5F683 ADC EAX,83F6B557

5. As we can see this is all just junk code at the moment.
6. Now we are going to use PCGuards unpacking routine against itself. PCGuard uses the TRAP FLAG while unpacking, maybe to interrupt tracing? Either way it is good for us!
**When the TRAP FLAG is set it puts the program into Single Step Mode, This creates a single-step break in the debugger, we will use those breaks to help us unpack this program.**
7. Go ahead and run the program. You will break on your first single-step break here:

CODE
007856DE EB 01 JMP SHORT Hypersco.007856E1
007856E0 D5 9D AAD 9D
007856E2 EB 01 JMP SHORT Hypersco.007856E5
007856E4 0BF8 OR EDI,EAX
007856E6 9C PUSHFD
007856E7 EB 01 JMP SHORT Hypersco.007856EA
007856E9 D5 9D AAD 9D
007856EB EB 01 JMP SHORT Hypersco.007856EE
007856ED 0B0F OR ECX,DWORD PTR DS:[EDI]

8. Take a quick look at the Hyperscore code section. (View->Memory. Double-click the [Hyperscore .code] section.) You will notice it is still packed.
9. Go ahead and press SHIFT+F9, this will pass the single-step exception to the program. You will break on another single-step break here:

CODE
00785A23 EB 01 JMP SHORT Hypersco.00785A26
00785A25 E3 60 JECXZ SHORT Hypersco.00785A87
00785A27 E8 03000000 CALL Hypersco.00785A2F
00785A2C D2EB SHR BL,CL
00785A2E 0B58 EB OR EBX,DWORD PTR DS:[EAX-15]
00785A31 0148 40 ADD DWORD PTR DS:[EAX+40],ECX
00785A34 EB 01 JMP SHORT Hypersco.00785A37
00785A36 35 FFE0E761 XOR EAX,61E7E0FF

10. .code section is still packed! Okay, Press SHIFT+F9 one more time. Olly will run for a little longer this time, a good sign! You will then break here:
CODE
007954EB EB 01 JMP SHORT Hypersco.007954EE
007954ED 89F7 MOV EDI,ESI
007954EF F7EB IMUL EBX
007954F1 01E3 ADD EBX,ESP
007954F3 EB 01 JMP SHORT Hypersco.007954F6
007954F5 D4 EB AAM 0EB
007954F7 A6 CMPS BYTE PTR DS:[ESI],BYTE PTR ES:[EDI]
007954F8 EB 01 JMP SHORT Hypersco.007954FB

11. Take a look at the Hyperscore .code section now. It should look like this:
CODE
00401000 56 PUSH ESI
00401001 8B7424 08 MOV ESI,DWORD PTR SS:[ESP+8]
00401005 6A FA PUSH -6
00401007 56 PUSH ESI
00401008 FF15 30E24600 CALL DWORD PTR DS:[46E230]
0040100E 6A 00 PUSH 0
00401010 68 30104000 PUSH Hypersco.00401030
00401015 56 PUSH ESI
00401016 68 CB000000 PUSH 0CB
0040101B 50 PUSH EAX
0040101C FF15 50E24600 CALL DWORD PTR DS:[46E250]
00401022 5E POP ESI
00401023 C3 RETN

12. Now that looks like unpacked code to me!
13. Well we know that the code section has now been unpacked, the next logical step for the unpacker is to jump to the OEP. We want to break when the program reaches the OEP. So we are going to put a breakpoint on the Hyperscore .code section. View->Memory. Choose [Hyperscore .code] and press F2 to set a breakpoint. Now Olly will break when the program accesses the newly unpacked code.
14. Press SHIFT+F9, Olly will break one more time on a Single-Step exception. Press SHIFT+F9 one last time. And you will now break here:

CODE
0046B6BA 55 PUSH EBP
0046B6BB 8BEC MOV EBP,ESP
0046B6BD 6A FF PUSH -1
0046B6BF 68 60074800 PUSH Hypersco.00480760
0046B6C4 68 68B84600 PUSH Hypersco.0046B868 ; JMP to msvcrt._except_handler3; SE handler installation
0046B6C9 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
0046B6CF 50 PUSH EAX
0046B6D0 64:8925 00000000 MOV DWORD PTR FS:[0],ESP
0046B6D7 83EC 68 SUB ESP,68
0046B6DA 53 PUSH EBX
0046B6DB 56 PUSH ESI
0046B6DC 57 PUSH EDI

15. That definately looks like an OEP! Go ahead and dump the file using OllyDump (make sure Rebuild imports is UNchecked). Save the file with any name you want.
16. Now leave Olly Open, open up IMPrec and choose Hyperscore from the dropdown menu. For the OEP put in your newley found OEP minus the Image Base. In my case my OEP was 0046B6BA the Image Base was 400000. (0046B6BA - 400000) = my OEP is 0006B6BA.
17. Press IAT AutoSearch and wait while the imported functions are found.
18. Now you can press FIX DUMP and choose the file you just dumped with Olly.
19. Close out Olly, and IMPrec and test out our new file... It Runs!!


Fixing SAVE and SAVE AS:

1. One of the first things you will notice when evaluating hyperscore is that SAVE and SAVE AS has been disabled. I will take you through enabling them.
2. Open your dumped Hyperscore in Olly. Press RUN
3. Wait while the program loads, when the activation box opens up just [X] out of it.
4. Okay time to play around. Go ahead and press the SAVE AS button and lets see what happens.
5. You will be presented with a message that says "You can't save Hyperscore files with this license". Well we will see about that. wink1.gif
6. Leave the messagebox open and switch back to Olly. Press the PAUSE button in Olly to stop Hyperscore's execution.
7. Now what we want to find out is how this messagebox was called. To do this we are going to use the CALL STACK.
8. In Olly, choose View->Call Stack. A new window will open and you should see the following:

Call stack of main thread
Address Stack Procedure / arguments Called from Frame
0012C7B4 77E33604 USER32.WaitMessage USER32.77E335FF 0012C7E4
0012C7E8 77E441D4 USER32.77E333EE USER32.77E441CF 0012C7E4
0012C80C 77E34110 USER32.77E44103 USER32.77E3410B 0012C808
0012CAC4 77E344AC USER32.SoftModalMessageBox USER32.77E344A7 0012CAC0
0012CC0C 77E3399F USER32.77E34265 USER32.77E3399A 0012CC08
0012CC64 77E34237 USER32.MessageBoxExW USER32.77E34232 0012CC60
0012CC68 00000000 hOwner = NULL
0012CC6C 01856680 Text = "You can't save Hyperscore
0012CC70 018567A8 Title = "Limited License Feature"
0012CC74 00042000 Style = MB_OK|MB_TASKMODAL|40000
0012CC78 00000000 LanguageID = 0 (LANG_NEUTRAL)
0012CC94 77E333D0 ? USER32.MessageBoxExA USER32.77E333CB 0012CC90
0012CC98 00000000 hOwner = NULL
0012CC9C 0012CCD4 Text = "You can't save Hyperscore
0012CCA0 011514F0 Title = "Limited License Feature"
0012CCA4 00042000 Style = MB_OK|MB_TASKMODAL|40000
0012CCA8 00000000 LanguageID = 0 (LANG_NEUTRAL)
0012CCB4 00414374 USER32.MessageBoxA Hypersco.0041436E 0012CCB0
0012CCB8 00000000 hOwner = NULL
0012CCBC 0012CCD4 Text = "You can't save Hyperscore
0012CCC0 011514F0 Title = "Limited License Feature"
0012CCC4 00042000 Style = MB_OK|MB_TASKMODAL|40000
0012D0D4 0041353E Hypersco.004142E0 Hypersco.00413539
0012D0D8 01150030 Arg1 = 01150030
0012D0DC 00000000 Arg2 = 00000000
0012D0E0 0040DE2E Hypersco.00413500 Hypersco.0040DE29 0012D71C
0012D0F8 0040D0F5 Includes Hypersco.0040DE2E Hypersco.0040D0F2 0012D71C
0012D50C 0040C6BB Hypersco.0040D090 Hypersco.0040C6B6
0012D510 001E03F2 Arg1 = 001E03F2
0012D514 00009C4C Arg2 = 00009C4C
0012D518 00000000 Arg3 = 00000000
0012D51C 00000000 Arg4 = 00000000

9. We can easily see where in the execution the program has definately decided we are unregistered:
CODE
0012CCBC 0012CCD4 Text = "You can't save Hyperscore
0012CCC0 011514F0 Title = "Limited License Feature"
0012CCC4 00042000 Style = MB_OK|MB_TASKMODAL|40000

10. So we know that the program decides our whether or not to let us save somewhere prior to that call.
11. You can double-click on some of the calls to see what each code location does. The Call we are interested in is this one: 0012D50C 0040C6BB Hypersco.0040D090 Hypersco.0040C6B6

12. How do I know? It was just trial and error, this call happened to lead to something interesting. Select the line with the call I've just shown you. Double click Hypersco.0040C6B6 in the CALLED FROM column. You will be here:
CODE
0040C692 |> 8B8424 5801000>MOV EAX,DWORD PTR SS:[ESP+158] ; Case 111 (WM_COMMAND) of switch 0040C4A2
0040C699 |. 8B8C24 5C01000>MOV ECX,DWORD PTR SS:[ESP+15C]
0040C6A0 |. 8BD0 MOV EDX,EAX
0040C6A2 |. 25 FFFF0000 AND EAX,0FFFF
0040C6A7 |. C1EA 10 SHR EDX,10
0040C6AA |. 52 PUSH EDX ; /Arg4
0040C6AB |. 8B96 C8000000 MOV EDX,DWORD PTR DS:[ESI+C8] ; |
0040C6B1 |. 51 PUSH ECX ; |Arg3
0040C6B2 |. 50 PUSH EAX ; |Arg2
0040C6B3 |. 52 PUSH EDX ; |Arg1
0040C6B4 |. 8BCE MOV ECX,ESI ; |
0040C6B6 |. E8 D5090000 CALL Hypersco.0040D090 ; \Hypersco.0040D090

13. Scrolling up a little will show you that this function is part of the handler for the programs window messages. You can see the WM_COMMAND, Scrolling down you will see WM_KEYDOWN and WM_DISPLAYCHANGE. When an action takes place in the programs window this part of code you have in front of you decides what to do with that action. If you press a key in hyperscore, the program will call WM_KEYDOWN and then act accordingly. If you move the mouse in hyperscore the WM_MOUSEMOVE function is called. And if you select a command from hyperscores drop-down menu the program calls WM_COMMAND.
14. We are going to figure out what happens between the program calling WM_COMMAND and the program deciding we cannot save. To do this we are going to break inside the WM_COMMAND function and step through the program. To do this, set a breakpoint on:
CODE
0040C6B6 |. E8 D5090000 CALL Hypersco.0040D090 ; \Hypersco.0040D090

15. Go ahead and press the RUN key again. And close out the Limited License Nag.
16. Now select FILE from Hyperscores menu and choose SAVE AS. We will break on the BP we just set. Step into the Call we set the breakpoint on and you should see the following:
CODE
0040D090 /$ 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8]
0040D094 |. 81EC 00040000 SUB ESP,400
0040D09A |. 53 PUSH EBX
0040D09B |. 56 PUSH ESI
0040D09C |. 8BF1 MOV ESI,ECX
0040D09E |. 57 PUSH EDI
0040D09F |. 8D88 B563FFFF LEA ECX,DWORD PTR DS:[EAX+FFFF63B5] ; Switch (cases 9C4B..9D09)
0040D0A5 |. 81F9 BE000000 CMP ECX,0BE
0040D0AB |. 0F87 94040000 JA Hypersco.0040D545
0040D0B1 |. 33D2 XOR EDX,EDX
0040D0B3 |. 8A91 38D64000 MOV DL,BYTE PTR DS:[ECX+40D638]
0040D0B9 |. FF2495 B8D5400>JMP NEAR DWORD PTR DS:[EDX*4+40D5B8] ; ***JUMPS BASED ON WHAT WE SELECTED IN HYPERSCORE***
0040D0C0 |> 8B8E 7C210000 MOV ECX,DWORD PTR DS:[ESI+217C] ; Case 9C4F of switch 0040D09F
0040D0C6 |. 8B01 MOV EAX,DWORD PTR DS:[ECX]
0040D0C8 |. FF50 58 CALL NEAR DWORD PTR DS:[EAX+58]
0040D0CB |. 5F POP EDI
0040D0CC |. 5E POP ESI
0040D0CD |. 5B POP EBX
0040D0CE |. 81C4 00040000 ADD ESP,400
0040D0D4 |. C2 1000 RETN 10
0040D0D7 |> 8B16 MOV EDX,DWORD PTR DS:[ESI] ; ***SAVE***; Case 9C4B of switch 0040D09F
0040D0D9 |. 6A 00 PUSH 0
0040D0DB |. 8BCE MOV ECX,ESI
0040D0DD |. FF52 50 CALL NEAR DWORD PTR DS:[EDX+50]
0040D0E0 |. 5F POP EDI
0040D0E1 |. 5E POP ESI
0040D0E2 |. 5B POP EBX
0040D0E3 |. 81C4 00040000 ADD ESP,400
0040D0E9 |. C2 1000 RETN 10
0040D0EC |> 8B06 MOV EAX,DWORD PTR DS:[ESI] ; ***SAVE AS***; Case 9C4C of switch 0040D09F
0040D0EE |. 6A 01 PUSH 1
0040D0F0 |. 8BCE MOV ECX,ESI
0040D0F2 |. FF50 50 CALL NEAR DWORD PTR DS:[EAX+50]
0040D0F5 |. 5F POP EDI
0040D0F6 |. 5E POP ESI
0040D0F7 |. 5B POP EBX
0040D0F8 |. 81C4 00040000 ADD ESP,400
0040D0FE |. C2 1000 RETN 10

17. I made a few comments in the code to help you understand it better. This is a switch-case method that jumps to a specific function based on what we chose in Hyperscore. If we picked SAVE in hyperscore instead of SAVE AS. This function would jump to this line: 0040D0D7 |> 8B16 MOV EDX,DWORD PTR DS:[ESI] ; ***SAVE***; Case 9C4B of switch 0040D09F

18. Effectively you can see how the menu of hyperscore works. Each menu item in Hyperscore has a value assigned to it.
Example:
-File Open = 1, Save = 2, and Save As = 3
-We choose Save As from the drop down menu.
-Hyperscore calls the WM_COMMAND function which takes the value of the menu item we chose and passes it to this function.
-This function then Jumps to a specified location based on the menu item's value.
- If we were edit the program so the value of File Open =3 and Save As = 1, then everytime we picked File Open from the menu we would get the Save As dialog.
19. Back to the code, the way I know which function is SAVE AS and which function is SAVE is because I picked the two on the menu and followed where this function jumped to. I'm letting you know to save you some time.
20. So we know that the SAVE AS function is called here:
CODE
0040D0EC |> 8B06 MOV EAX,DWORD PTR DS:[ESI] ; ***SAVE AS***; Case 9C4C of switch 0040D09F
0040D0EE |. 6A 01 PUSH 1
0040D0F0 |. 8BCE MOV ECX,ESI
0040D0F2 |. FF50 50 CALL NEAR DWORD PTR DS:[EAX+50]
0040D0F5 |. 5F POP EDI
0040D0F6 |. 5E POP ESI
0040D0F7 |. 5B POP EBX
0040D0F8 |. 81C4 00040000 ADD ESP,400
0040D0FE |. C2 1000 RETN 10

We can see that the program doesn't test our license in this little piece of code. Instead the program must test the license value somewhere inside this CALL: 0040D0F2 |. FF50 50 CALL NEAR DWORD PTR DS:[EAX+50]

21. Go ahead and put a breakpoint on this CALL and press RUN. When you break, press the step into button. You should be here:
CODE
0040DE10 53 PUSH EBX
0040DE11 55 PUSH EBP
0040DE12 56 PUSH ESI
0040DE13 8BD9 MOV EBX,ECX
0040DE15 E8 364B0000 CALL Hypersco.00412950
0040DE1A 8BC8 MOV ECX,EAX
0040DE1C E8 9F500000 CALL Hypersco.00412EC0
0040DE21 84C0 TEST AL,AL
0040DE23 75 12 JNZ SHORT Hypersco.0040DE37
0040DE25 6A 00 PUSH 0
0040DE27 6A 14 PUSH 14
0040DE29 E8 D2560000 CALL Hypersco.00413500
0040DE2E 83C4 08 ADD ESP,8
0040DE31 5E POP ESI
0040DE32 5D POP EBP
0040DE33 5B POP EBX
0040DE34 C2 0400 RETN 4

*If your code looks all wierd, Right-Click->Analysis->Remove Analysis from Module*
22. Hmm, this code looks interesting. There two CALLs then a TEST then a JNZ. If the jump is not taken another CALL is made, however if the jump IS taken we will jump down below the RETN to here:
CODE
0040DE37 8B83 88210000 MOV EAX,DWORD PTR DS:[EBX+2188]
0040DE3D 8B8B 84210000 MOV ECX,DWORD PTR DS:[EBX+2184]
0040DE43 8B93 8C210000 MOV EDX,DWORD PTR DS:[EBX+218C]
0040DE49 8983 DC250000 MOV DWORD PTR DS:[EBX+25DC],EAX
0040DE4F 8A4424 10 MOV AL,BYTE PTR SS:[ESP+10]
0040DE53 8DAB A0210000 LEA EBP,DWORD PTR DS:[EBX+21A0]
0040DE59 84C0 TEST AL,AL

Scrolling down a bit in the code window you will notice an interesting CALL:
CODE
0040DF73 FF15 50E34600 CALL NEAR DWORD PTR DS:[<&comdlg32.GetSa>; comdlg32.GetSaveFileNameA

23. Back to the code we are at:
CODE
0040DE1C E8 9F500000 CALL Hypersco.00412EC0
0040DE21 84C0 TEST AL,AL
0040DE23 75 12 JNZ SHORT Hypersco.0040DE37

If the JNZ is not taken then we will never call GetSaveFileNameA, instead we will make a CALL to some other place in code and RETN to the program.
24. However, if we change that JNZ to a JMP it will always jump to the SAVE AS routine! That is what we are going to do. Choose JNZ SHORT Hypersco.0040DE37 and press SPACE to Assemble. In the box that opens up, change JNZ SHORT Hypersco.0040DE37 into JMP SHORT Hypersco.0040DE37 and press Assemble.
25. Okay, time to test it out! We are still at the beginning of the Save As routine so go ahead and press RUN to see what happens. Give the program a minute... And we are presented with a SAVE AS dialog box. We did it!
26. The steps we took above also enabled the SAVE menu command too. So we are a little bit close to a full working version.
27. We can now fix the other limitations of the program using the same technique.
The other limitations are: the length of the sketch window and the amount of motives we can add/edit.
28. We can start with the length of the sketch window; Add a sketch window, now grab the end of the window and try and drag it to the right. You will get an error message saying: "You can't make a sketch window that is longer..."
29. Leave that error message up and go back to Olly. View the Call Stack again. you should see:
Call stack of main thread
0012CB70 77E33604 USER32.WaitMessage USER32.77E335FF 0012CBA0
0012CBA4 77E441D4 USER32.77E333EE USER32.77E441CF 0012CBA0
0012CBC8 77E34110 USER32.77E44103 USER32.77E3410B 0012CBC4
0012CE80 77E344AC USER32.SoftModalMessageBox USER32.77E344A7 0012CE7C
0012CFC8 77E3399F USER32.77E34265 USER32.77E3399A 0012CFC4
0012D020 77E34237 USER32.MessageBoxExW USER32.77E34232 0012D01C
0012D024 00000000 hOwner = NULL
0012D028 001900E8 Text = "You can't make a sketch wi
0012D02C 00190250 Title = "Limited License Feature"
0012D030 00042000 Style = MB_OK|MB_TASKMODAL|40000
0012D034 00000000 LanguageID = 0 (LANG_NEUTRAL)
0012D050 77E333D0 ? USER32.MessageBoxExA USER32.77E333CB 0012D04C
0012D054 00000000 hOwner = NULL
0012D058 0012D090 Text = "You can't make a sketch wi
0012D05C 0116FF90 Title = "Limited License Feature"
0012D060 00042000 Style = MB_OK|MB_TASKMODAL|40000
0012D064 00000000 LanguageID = 0 (LANG_NEUTRAL)
0012D070 00414374 USER32.MessageBoxA Hypersco.0041436E 0012D06C
0012D074 00000000 hOwner = NULL
0012D078 0012D090 Text = "You can't make a sketch wi
0012D07C 0116FF90 Title = "Limited License Feature"
0012D080 00042000 Style = MB_OK|MB_TASKMODAL|40000
0012D490 0041353E Hypersco.004142E0 Hypersco.00413539
0012D494 011CE35C Arg1 = 011CE35C
0012D498 00000000 Arg2 = 00000000
0012D49C 0042DA60 Hypersco.00413500 Hypersco.0042DA5B 0012D71C
0012D500 0042121A Includes Hypersco.0042DA60 Hypersco.00421217 0012D71C
0012D50C 0040C2E2 Includes Hypersco.0042121A Hypersco.0040C2DF 0012D71C
0012D51C 0040C8BB Hypersco.0040C230 Hypersco.0040C8B6 0012D71C
0012D670 0040A218 Hypersco.0040C420 Hypersco.0040A213 0012D71C

30. The call stack we see now looks very similar to the call stack that we had for the Save/Save As. Which means it is deciding we are registered somewhere before
CODE
0012D070 00414374 USER32.MessageBoxA Hypersco.0041436E 0012D06C
0012D074 00000000 hOwner = NULL
0012D078 0012D090 Text = "You can't make a sketch wi
0012D07C 0116FF90 Title = "Limited License Feature"
0012D080 00042000 Style = MB_OK|MB_TASKMODAL|40000

31. I have already gone through some of the calls, but if you are interested click on different calls to see where in the program they take you. The one that takes you to the message handler for the hyperscore window is this one:
CODE
0012D51C 0040C8BB Hypersco.0040C230 Hypersco.0040C8B6 0012D71C

32. But rather than trace through the hyperscore code again we can look at the call stack and easily see where we go.

Hypersco.0040C8B6 is the message handler and it calls Hypersco.0040C230
Since this is just the usual function of the message handler we can assume the function at Hypersco.0040C230 won't decide if we are registered. However looking at the call stack we see:
CODE
0012D50C 0040C2E2 Includes Hypersco.0042121A Hypersco.0040C2DF 0012D71C

33. So inside the function called from the message handler there is a CALL at Hypersco.0040C2DF which CALLs the function at Hypersco.0042121A. Probably somewhere in there our registration check is made. Double click the: Includes Hypersco.0042121A and you will find yourself here:
**Scroll up so your code matches mine**
CODE
00421213 > 8B0E MOV ECX,DWORD PTR DS:[ESI]
00421215 . 8B01 MOV EAX,DWORD PTR DS:[ECX]
00421217 . FF50 60 CALL NEAR DWORD PTR DS:[EAX+60]***AFTER THE JUMP WE WILL EXECUTE THIS CALL***
0042121A . 8B76 04 MOV ESI,DWORD PTR DS:[ESI+4] ***WE ARE STARTING HERE***
0042121D . 85F6 TEST ESI,ESI ***A TEST IS MADE***
0042121F .^75 F2 JNZ SHORT Hypersco.00421213 ***WE WILL JUMP BACK UP TO 00421213***
00421221 > 5F POP EDI
00421222 . 5E POP ESI
00421223 . C3 RETN

34. We can see from the code and my comments what exactly happens here. We start at 0042121A and then have a TEST and then a JUMP to 00421213, a few things are MOVed and then we have a CALL at 00421217. But where does this call go to? We cannot tell by the code because it is dependent on the value of EAX at the time. However we can tell by looking at our CALL STACK again. Look at this line:
CODE
0012D500 0042121A Includes Hypersco.0042DA60 Hypersco.00421217 0012D71C

35. We see that the CALL at 00421217 CALLed the function at Hypersco.0042DA60. Go ahead and double click: Includes Hypersco.0042DA60. You will be here in the code:

CODE
0042DA60 . 83C4 08 ADD ESP,8
0042DA63 . 85C0 TEST EAX,EAX
0042DA65 74 25 JE SHORT Hypersco.0042DA8C
0042DA67 . 8B4E 20 MOV ECX,DWORD PTR DS:[ESI+20]

36. Scroll up in the code window and you will hopefully see something familiar:
CODE
0042DA29 . E8 224FFEFF CALL Hypersco.00412950
0042DA2E . 8BC8 MOV ECX,EAX
0042DA30 . E8 CB54FEFF CALL Hypersco.00412F00
0042DA35 . 3B05 30E84600 CMP EAX,DWORD PTR DS:[46E830]
0042DA3B 74 4F JE SHORT Hypersco.0042DA8C

which looks a lot like the SAVE/SAVE AS compare for our registration:
CODE
0040DE15 E8 364B0000 CALL Hypersco.00412950
0040DE1A 8BC8 MOV ECX,EAX
0040DE1C E8 9F500000 CALL Hypersco.00412EC0
0040DE21 84C0 TEST AL,AL
0040DE23 75 12 JNZ SHORT Hypersco.0040DE37

37. Maybe the same trick will work: Select: JE SHORT Hypersco.0042DA8C and press SPACE to ASSEMBLE. In the box that opens up type JMP SHORT Hypersco.0042DA8C. It will now JUMP over all the nags and go straight to the real code.
38. Press RUN and close out that annoying messagebox. Now try extending the Sketch window... Hey we can now make it any length we want!
39. I will not walk you through fixing the motive limitations. Instead I will tell you that it is very similar to fixing all the other limiations of this program. Use the CALL STACK, look for this generic sequence:

CODE
0041FEC3 . E8 882AFFFF CALL Hypersco.00412950
0041FEC8 . 8BC8 MOV ECX,EAX
0041FECA . E8 0130FFFF CALL Hypersco.00412ED0
0041FECF . 8B4E 68 MOV ECX,DWORD PTR DS:[ESI+68]
0041FED2 . 85C9 TEST ECX,ECX
0041FED4 . 74 0D JE SHORT Hypersco.0041FEE3

And change the conditional jump to always jump over the registration nag code.

**HINT: For fixing the amount of motives you will make it always JMP. Fixing the Editing limitation of the motives requires NOP'ing 1 JUMP and changing 1 conditional JMP:**
0041FEC3 . E8 882AFFFF CALL Hypersco.00412950
0041FEC8 . 8BC8 MOV ECX,EAX
0041FECA . E8 0130FFFF CALL Hypersco.00412ED0
0041FECF . 8B4E 68 MOV ECX,DWORD PTR DS:[ESI+68]
0041FED2 . 85C9 TEST ECX,ECX
0041FED4 74 0D JE SHORT Hypersco.0041FEE3 **NOP THIS***
0041FED6 . 3B05 30E84600 CMP EAX,DWORD PTR DS:[46E830]
0041FEDC . 74 28 JE SHORT Hypersco.0041FF06 **ALWAYS JUMP**
0041FEDE . 3941 1C CMP DWORD PTR DS:[ECX+1C],EAX
0041FEE1 . 7C 23 JL SHORT Hypersco.0041FF06

40. We covered unpacking PC-Guard 5.0 by using the exceptions generated by the unpacking routine. And we also covered how the CALL STACK can be used to reverse a programs protection scheme. We finally learned to look for common functions within a program and when we recognize them we can use them to defeat the protection.

 

Conclusion:

I used this particular program purely as a demonstration for unpacking and patching. Please if you like the program and are going to use it please purchase it.

ARTeam has hit 100+ tutorials!
Thanks to the whole ARTeam:
[Nilrem] [JDog45] [Shub - Nigurrath] [MaDMAn_H3rCuL3s] [Ferrari] [Kruger] [Teerayoot] [R@dier] [ThunderPwr] [Eggi] [EJ12N] [Gabri3l]
[Stickman 373] [Bone Enterprise]

Thanks to all the people who take time to write tutorials.
Thanks to all the people who continue to develop better tools.
Thanks to Exetools and Woodmann for being a great place of learning.
Thanks also to The Codebreakers Journal, and the Anticrack forum.
Thanks to all the great teams and their members: SND, TSRH, MP2K, ICU and all the others.

If you have any suggestions, comments or corrections email me: Gabri3l2003[at]yahoo.com